package com.dwy2002.common.utils;

import com.alibaba.fastjson2.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

/**
 * Jwt工具类
 *
 * @author 杜伟毅
 * @version 1.0
 * @since 2023/10/09
 */
@Component
public class JwtUtil {

    /**
     * 有效期
     */
    private static final long JWT_CONSUMER_EXPIRE = 2592000000L;//一个月
    /**
     * 令牌秘钥
     */
    private static final String JWT_KEY = "eyJhbGciOiJIUzI1NiJ9";

    /**
     * 生成token
     *
     * @param data 数据
     * @return 对函数返回值的描述
     * @author 杜伟毅
     * @since 2023/10/12 0012 15:13
     */
    public String createToken(Object data) {
        // 当前时间
        long currentTime = System.currentTimeMillis();
        // 过期时间
        long expTime = currentTime + JWT_CONSUMER_EXPIRE;
        // 构建jwt
        JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID() + "")//设置唯一id
                .setSubject(JSON.toJSONString(data))//设置主体
                .setIssuer("system")//设置签发者
                .setIssuedAt(new Date(currentTime))//设置签发时间
                .signWith(SignatureAlgorithm.HS256, encodeSecret(JWT_KEY))//设置加密算法和密钥
                .setExpiration(new Date(expTime));//设置过期时间
        return builder.compact();
    }

    /**
     * 其目的是将一个字符串（key）编码为一个SecretKey对象，特别是用于AES加密
     *
     * @param key 钥匙
     * @return 对函数返回值的描述
     * @author 杜伟毅
     * @since 2024/11/2 0002 15:28
     */
    private SecretKey encodeSecret(String key) {
        byte[] encode = Base64.getEncoder().encode(key.getBytes());
        SecretKeySpec aes = new SecretKeySpec(encode, 0, encode.length, "AES");
        return aes;
    }

    /**
     * 解析token(可以直接返回Users对象)
     *
     * @param token token
     * @return 对函数返回值的描述
     * @author 杜伟毅
     * @since 2024/11/2 0002 15:27
     */
    public <T> T parseToken(String token, Class<T> clazz) {
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY))
                .parseClaimsJws(token)
                .getBody();
        return JSON.parseObject(body.getSubject(), clazz);
    }
}
